home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / The World of Computer Software.iso / gs241j11.zip / ZIMPATH.C < prev    next >
C/C++ Source or Header  |  1992-05-02  |  6KB  |  329 lines

  1. /*
  2.  * Bitmap Image Utility Routines
  3.  *
  4.  * Copyright (C) 1991 Norio Katayama.
  5.  * Aug. 28, 1991 Programmed by N.Katayama (katayama@nacsis.ac.jp)
  6.  */
  7.  
  8. #include "memory_.h"
  9. #include "ghost.h"
  10. #include "oper.h"
  11. #include "errors.h"
  12. #include "gsmatrix.h"
  13. #include "gspath.h"
  14. #include "state.h"
  15. #include "store.h"
  16.  
  17. /* Forward declaration */
  18.  
  19. int gs_imagebbox(P6(int, int, int, gs_matrix *, byte *, gs_rect *));
  20. private int imagepath(P5(int, int, int, gs_matrix *, byte *));
  21. private int trace_path(P6(byte *bp, int, int, int, gs_matrix *, int));
  22.  
  23. /*
  24.  * imagepath
  25.  */
  26.  
  27. int
  28. zimagepath(register os_ptr op)
  29. {
  30.     int code;
  31.     gs_matrix mat;
  32.  
  33.     check_type(op[-4], t_integer);
  34.     check_type(op[-3], t_integer);
  35.     check_type(op[-2], t_boolean);
  36.     if((code = read_matrix(op - 1, &mat)) < 0)
  37.         return code;
  38.     check_type(*op, t_string);
  39.  
  40.     if((code = 
  41.         imagepath((int)op[-4].value.intval, (int)op[-3].value.intval, 
  42.               (int)op[-2].value.index, &mat, op[0].value.bytes)) < 0)
  43.         return code;
  44.  
  45.     pop(5);
  46.     return 0;
  47. }
  48.  
  49. /*
  50.  * imagebbox
  51.  */
  52.  
  53. int
  54. zimagebbox(register os_ptr op)
  55. {
  56.     int code;
  57.     gs_rect bbox;
  58.     gs_matrix mat;
  59.  
  60.     check_type(op[-4], t_integer);
  61.     check_type(op[-3], t_integer);
  62.     check_type(op[-2], t_boolean);
  63.     if((code = read_matrix(op - 1, &mat)) < 0)
  64.         return code;
  65.     check_type(*op, t_string);
  66.  
  67.     if((code = 
  68.         gs_imagebbox((int)op[-4].value.intval, (int)op[-3].value.intval, 
  69.              (int)op[-2].value.index, &mat, op[0].value.bytes,
  70.              &bbox)) < 0)
  71.         return code;
  72.  
  73.     pop(1);
  74.     op --;
  75.     make_real(op - 3, bbox.p.x);
  76.     make_real(op - 2, bbox.p.y);
  77.     make_real(op - 1, bbox.q.x);
  78.     make_real(op, bbox.q.y);
  79.     return 0;
  80. }
  81.  
  82. /* -------- Initialization procedure -------- */
  83.  
  84. op_def zimpath_op_defs[] = {
  85.     {"5imagepath", zimagepath},
  86.     {"5imagebbox", zimagebbox},
  87.     op_def_end(0)
  88. };
  89.  
  90. /* -------- Library routines -------- */
  91.  
  92. /*
  93.  * Retrieve the boundary box of bitmap image
  94.  */
  95.  
  96. int
  97. gs_imagebbox(int width, int height, int bool, 
  98.          gs_matrix *pmat, byte *image, gs_rect *pbbox)
  99. {
  100.     int code, x, y, offx, offy;
  101.     int width8 = width / 8 + (width % 8 ? 1 : 0);
  102.     int minx, miny, maxx, maxy;
  103.     byte mask;
  104.     gs_matrix imat;
  105.  
  106.     minx = width;
  107.     maxx = 0;
  108.     miny = height;
  109.     maxy = 0;
  110.  
  111.     for(y=0, offy=0; y<height; y++, offy+=width8) {
  112.         mask = 0x80;
  113.         for(x=0, offx=offy; x<width; x++) {
  114.             if((image[offx] & mask) ? bool : !bool) {
  115.                 if(x < minx)
  116.                     minx = x;
  117.                 if(x > maxx)
  118.                     maxx = x;
  119.                 if(y < miny)
  120.                     miny = y;
  121.                 if(y > maxy)
  122.                     maxy = y;
  123.             }
  124.             if((mask = (mask >> 1)) == 0) {
  125.                 mask = 0x80;
  126.                 offx ++;
  127.             }
  128.         }
  129.     }
  130.     
  131.     if((code = gs_matrix_invert(pmat, &imat)) < 0)
  132.         return code;
  133.  
  134.     gs_point_transform((floatp)minx, (floatp)miny, &imat, &pbbox->p);
  135.     gs_point_transform((floatp)maxx+1, (floatp)maxy+1, &imat, &pbbox->q);
  136.  
  137.     if(pbbox->p.x > pbbox->q.x) {
  138.         floatp temp;
  139.         temp = pbbox->p.x;
  140.         pbbox->p.x = pbbox->q.x;
  141.         pbbox->q.x = temp;
  142.     }
  143.     if(pbbox->p.y > pbbox->q.y) {
  144.         floatp temp;
  145.         temp = pbbox->p.y;
  146.         pbbox->p.y = pbbox->q.y;
  147.         pbbox->q.y = temp;
  148.     }
  149.  
  150.     return 0;
  151. }
  152.  
  153. /* -------- Internal routines -------- */
  154.  
  155. /*
  156.  * imagepath
  157.  */
  158.  
  159. #define BIT_ON        0x01
  160. #define WEST_EDGE_DONE    0x02
  161. #define FIRST_BIT    0x04
  162.  
  163. #define moveto(x, y)    { gs_point pt; \
  164.     gs_point_transform((float)(x)/4.0, (float)(y)/4.0, pmat, &pt); \
  165.     gs_moveto(igs, pt.x, pt.y); }
  166.  
  167. #define lineto(x, y)    { gs_point pt; \
  168.     gs_point_transform((float)(x)/4.0, (float)(y)/4.0, pmat, &pt); \
  169.     gs_lineto(igs, pt.x, pt.y); }
  170.  
  171. #define closepath()    gs_closepath(igs)
  172.  
  173. private int
  174. imagepath(int width, int height, int fine, gs_matrix *pmat, byte *image)
  175. {
  176.     byte *bitmap, *bpx, *bpy;
  177.     int code, x, y, offx, offy;
  178.     int width8 = width / 8 + (width % 8 ? 1 : 0);
  179.     int bwidth = width + 2;
  180.     int bheight = height + 2;
  181.     int bsize = bwidth*bheight;
  182.     byte mask;
  183.     gs_matrix imat;
  184.  
  185.     if((code = gs_matrix_invert(pmat, &imat)) < 0)
  186.         return code;
  187.  
  188.     if((bitmap = (byte *)gs_malloc(1, bsize, "imagepath(bitmap)")) == 0)
  189.         return e_VMerror;
  190.     memset(bitmap, 0, bsize);
  191.  
  192.     for(y=0, bpy=bitmap+bwidth, offy=0; y<height; 
  193.         y++, bpy+=bwidth, offy+=width8) {
  194.         mask = 0x80;
  195.         for(x=0, bpx=bpy+1, offx=offy; x<width; x++, bpx++) {
  196.             if(image[offx] & mask)
  197.                 *bpx = 1;
  198.             if((mask = (mask >> 1)) == 0) {
  199.                 mask = 0x80;
  200.                 offx ++;
  201.             }
  202.         }
  203.     }
  204.     
  205.     for(y=0, bpy=bitmap+bwidth; y<height; y++,bpy+=bwidth) {
  206.         for(x=0, bpx=bpy+1; x<width; x++, bpx++) {
  207.             if(*(bpx - 1) == 0 && *bpx == BIT_ON)
  208.                 trace_path(bpx, bwidth, x, y, &imat, fine);
  209.         }
  210.     }
  211.  
  212.     gs_free((char *)bitmap, 1, bsize, "imagepath(bitmap)");
  213.     return 0;
  214. }
  215.  
  216. private int
  217. trace_path(byte *bp, int bwidth, int x, int y, gs_matrix *pmat, int fine)
  218. {
  219. #define EAST    0
  220. #define SOUTH    1
  221. #define WEST    2
  222. #define NORTH    3
  223.     static int bd[] = {
  224.         1,        /* east */
  225.         -1,        /* south */
  226.         -1,        /* west */
  227.         1,        /* north */
  228.     };
  229.     static struct xy {
  230.         int x, y;
  231.     } xy[] = {
  232.         { 1, 0 },    /* east */
  233.         { 0, -1 },    /* south */
  234.         { -1, 0 },    /* west */
  235.         { 0, 1 },    /* north */
  236.     };
  237.     int edge = WEST;
  238.     int dir = NORTH;
  239.     int straight = 0;
  240.     int ex, ey, dx, dy;
  241.     int bd_edge, bd_dir;
  242.     int temp;
  243.  
  244.     bd[NORTH] = bwidth;
  245.     bd[SOUTH] = -bwidth;
  246.     x = x*4;
  247.     y = y*4 + 2;
  248.     moveto(x, y);
  249.     
  250.     *bp |= FIRST_BIT;
  251.     do {
  252.         if(edge == WEST)
  253.             *bp |= WEST_EDGE_DONE;
  254.         ex = xy[edge].x;
  255.         ey = xy[edge].y;
  256.         dx = xy[dir].x;
  257.         dy = xy[dir].y;
  258.         bd_edge = bd[edge];
  259.         bd_dir = bd[dir];
  260.         if(*(bp + bd_dir + bd_edge)) {
  261.             if(fine) {
  262.                 if(*(bp + bd_dir)) {
  263.                     x += dx;
  264.                     y += dy;
  265.                     lineto(x, y);
  266.                     x += dx + ex;
  267.                     y += dy + ey;
  268.                     lineto(x, y);
  269.                     x += ex;
  270.                     y += ey;
  271.                 }
  272.                 else {
  273.                     lineto(x, y);
  274.                     x += (dx << 1) + (ex << 1);
  275.                     y += (dy << 1) + (ey << 1);
  276.                     lineto(x, y);
  277.                 }
  278.             }
  279.             else {
  280.                 if(straight)
  281.                     lineto(x, y);
  282.                 x += (dx << 1) + (ex << 1);
  283.                 y += (dy << 1) + (ey << 1);
  284.                 lineto(x, y);
  285.             }    
  286.             bp += bd_dir + bd_edge;
  287.             temp = edge;
  288.             edge = (dir + 2) & 3;
  289.             dir = temp;
  290.             straight = 0;
  291.         }
  292.         else if(*(bp + bd_dir)) {
  293.             x += dx << 2;
  294.             y += dy << 2;
  295.             bp += bd_dir;
  296.             straight = 1;
  297.         }
  298.         else {
  299.             if(fine) {
  300.                 x += dx;
  301.                 y += dy;
  302.                 lineto(x, y);
  303.                 x += dx - ex;
  304.                 y += dy - ey;
  305.                 lineto(x, y);
  306.                 x += - ex;
  307.                 y += - ey;
  308.             }
  309.             else {
  310.                 if(straight)
  311.                     lineto(x, y);
  312.                 x += (dx << 1) - (ex << 1);
  313.                 y += (dy << 1) - (ey << 1);
  314.                 lineto(x, y);
  315.             }
  316.             temp = edge;
  317.             edge = dir;
  318.             dir = (temp + 2) & 3;
  319.             straight = 0;
  320.         }
  321.     } while( edge != WEST || !(*bp & FIRST_BIT));
  322.     closepath();
  323.     *bp &= ~FIRST_BIT;
  324.     return 0;
  325. }
  326.  
  327.  
  328.  
  329.